/*
 * GeoVISTA Center (Penn State, Dept. of Geography)
 * Copyright (c) 2002, GeoVISTA Center
 * Licensed under Simplified BSD License
 * This library is developed and distributed for free usage,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * You can redistribute and/or modify it under the terms of the
 * Simplified BSD License
 *
 *
 *
 *
 *
 *
 *
 * @original author: jin Chen 
 * @author: jin Chen 
 * @date: Nov 10, 2008$
 * @version: 1.0
 */
package edu.psu.geovista.app.vit.pub.views;

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import edu.psu.geovista.app.coordinator.CoordinationManager;
import edu.psu.geovista.app.dataloader.v1.DataLoaders;
import edu.psu.geovista.app.dataloader.v1.session.ProjectBuilder;
import edu.psu.geovista.app.gmap.SimpleGeoMap;
import edu.psu.geovista.app.pcp.DfPcp;
import edu.psu.geovista.app.scatterplot.SimpleScatterPlot;
import edu.psu.geovista.app.visualclassifier.classify.v2.DefaultESVisualClassifier;
import edu.psu.geovista.app.vit.pub.VitPub;
import edu.psu.geovista.data.model.AppDataModel;
import edu.psu.geovista.data.model.DefaultAppDataModel;
import epoviz.trex.common.swing.components.internalframe.SimpleInternalFrame;
import epoviz.trex.common.swing.frame.AppComponent;
import epoviz.trex.common.swing.frame.workspace.xml.XStreamSerializer;
import epoviz.trex.common.xml.xstream.XSerializable;
import org.safehaus.uuid.UUIDGenerator;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;

public class VitPubViewMgr implements XSerializable {

     public static final String COMPONENT_ROOT="components";

    //constant
    transient String viewprex="View ";
    transient Rectangle componentLayout=new Rectangle(100,100,800,600);
    //view
    transient String projectRoot;//root path of the project
    transient VitPub app;
    transient Map<String, JComponent> viewComponents;// 
    transient Map <String, JComponent> viewFrames;//  
    Map <String, View> views;  //view ID, ---> view. serialize
    

    public VitPubViewMgr() {
    }

    public VitPubViewMgr(VitPub app) {

        this.app = app;
       viewComponents=new HashMap<String, JComponent>();
       viewFrames=new HashMap<String, JComponent>();
        views=new HashMap<String, View>();

    }

    public JComponent getViewComponent(String ID){
        return  viewComponents.get(ID);
    }
      /**
     * see also createView
     * @param v
     */
    public void addView(View v){
        this.views.put(v.getName() ,v);
        //this.save();
    }
    public void removeView(String viewname){
        View view = this.getView(viewname);
        if(view==null){
            System.out.println(" Opps, no view is found with name "+viewname);
            return;
        }
        String id = view.getID();
        JComponent vcomp = view.getViewComponent();
        if(getCoordMgr() !=null&&vcomp!=null)
            getCoordMgr().removeBean(vcomp)    ;
        viewComponents.remove(id);
        VitPub app = getApp();
        JDesktopPane desktop = app.getDesktop();
        JComponent vwfrm = viewFrames.get(id);
        desktop.remove(vwfrm);
        desktop.revalidate();
        desktop.repaint();
        this.viewFrames.remove(id);
        this.views.remove(id) ;
       // this.save();

    }
    /**************************************************
     *                create views
     ***************************************************/
    public View createView(String vwname, String  viewtype){
        View view = createView();
        view.setName(vwname);
        view.setViewType(viewtype);
        view.setViewMgr(this);
        
        views.put(view.getID(),view); //put view first, then set data
        createViewComponent(view);
        return view;
    }
    protected View createView(){
        BasicView view=new BasicView();
        StringBuffer sb=new StringBuffer();
        sb.append('V'); sb.append('i'); sb.append('e'); sb.append('w');
        sb.append(UUIDGenerator.getInstance().generateTimeBasedUUID().toString());
        String id=sb.toString();
        view.setID(id);
        view.setBound(componentLayout);
        return view;
    }
    private void createViewComponent(View view) {
      //  DesktopApplication app = (DesktopApplication) getApp();
        JDesktopPane desktop = app.getDesktop();
        JComponent comp =null;
        String  viewtype = view.getViewType();
        if(viewtype.equals(View.TYPE_GEOMAP)){
            comp=new SimpleGeoMap();
        }
        else if (viewtype.equals(View.TYPE_PCP)){
            comp=new DfPcp();
        }
        else if (viewtype.equals(View.TYPE_SCATTERPLOT)){
            comp=new SimpleScatterPlot();
        }
        else if (viewtype.equals(View.TYPE_Classifier)){
            comp=new DefaultESVisualClassifier();
        }
        else if (viewtype.equals(View.TYPE_TABLE)){
            comp=new JTable();

        }
        Rectangle layout = view.getBound();
        viewComponents.put(view.getID(),comp);
       AppDataModel dataModel = this.app.getDataModel();

        SimpleInternalFrame frm = null;
        if (viewtype.equals(View.TYPE_TABLE)){
               JScrollPane sp=new JScrollPane(comp);
              frm = SimpleInternalFrame.addComponent(desktop, sp, view.getName(), layout.getSize());
        }
        else{
             frm = SimpleInternalFrame.addComponent(desktop, comp, view.getName(), layout.getSize());
        }
        frm.setLocation(layout.getLocation());
        viewFrames.put(view.getID(),frm);

        if(viewtype.equals(View.TYPE_TABLE)){
            DefaultTableModel tablemodel = DefaultAppDataModel.getTableModel((DefaultAppDataModel) dataModel);
            JTable table= (JTable) comp;
            table.setModel(tablemodel);
        }
        else{
            //set view with data
            try { // 

                AppComponent appComp= (AppComponent) comp;
                appComp.setDataModel(dataModel);
            } catch (Exception e) {
                System.err.println("Exception occur when create view component for view "+view.getName() );
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }

        JComponent vcomp = view.getViewComponent();
        this.getCoordMgr().addBean(vcomp);// 



    }
    public View getView(String vwname){
            Map<String, View> viewmap = this.getViews();
            Collection<View> views1 = viewmap.values();
            for (Iterator iterator = views1.iterator(); iterator.hasNext();) {
                View view = (View) iterator.next();
                if(view.getName().equals(vwname) ){
                    return view;
                }
            }
            return null;
        }
     public Map<String, View> getViews() {
        return views;
    }
      public VitPub getApp() {
        return app;
    }

    public void save() throws IOException {
        Set<String> ids = viewFrames.keySet();
        for (Iterator iterator = ids.iterator(); iterator.hasNext();) {
            String id = (String) iterator.next();
            SimpleInternalFrame frm = (SimpleInternalFrame) viewFrames.get(id);
            Rectangle bd = frm.getBounds();
            View view = this.views.get(id);
            view.setBound(bd);
         /*   if(view.isSave()){
                this.views.remove(id);
            }*/

        }
        XStreamSerializer persist=new XStreamSerializer();
         persist.setObject(this);
        persist.setStringAsAttribute(true);
        persist.save(this);//save this project in a xml file
    }

    /*public Object load(File file) throws FileNotFoundException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }*/

    public void load() throws FileNotFoundException {
        String fn = getPersistentFileName();
         File file = new File(fn);
         if(file.exists() )
            load(file);
    }
  public Object load(File file) throws FileNotFoundException {
     
        XStreamSerializer persist=new XStreamSerializer();
        persist.setObject(this);
        persist.setStringAsAttribute(true);
        XSerializable me = new VitPubViewMgr();
        VitPubViewMgr aViewMgr = (VitPubViewMgr)  persist.load(me, file);

        Map<String, View> viewmap = aViewMgr.getViews();
        this.setViews(viewmap);

         Collection<View> viewlists = viewmap.values();

        for (Iterator iterator = viewlists.iterator(); iterator.hasNext();) {
            View view = (View) iterator.next();
            view.setViewMgr(this);

            this.createViewComponent(view);
            System.out.println(this.getClass().getName() +" create view "+ view.getName() +"["+view.getViewType() +"]");
        }
        System.out.println(this.getClass().getName() + " load views <--");
      
        return aViewMgr;
    }

    public Class[] getAliasClasses() {
        return new Class[]{BasicView.class};
    }

    public Converter[] getConvertor() {
        return new Converter[0];  //To change body of implemented methods use File | Settings | File Templates.
    }

    public SingleValueConverter[] getSingleValueConvertor() {
        return new SingleValueConverter[0];  //To change body of implemented methods use File | Settings | File Templates.
    }

    public String getPersistentFileName() {
        String root = getRoot();

        return root+File.separator +"viewmgr.xml";//"F:/temp/viewmgr.xml";  //To change body of implemented methods use File | Settings | File Templates.
    }

    public  String getRoot() {
        DataLoaders ld = this.app.getDataloader();
        String pjn = ld.getCurrentProjectName();
        String ws = ProjectBuilder.getWorkspaceRoot();

        String root = ws+pjn;
        return root;
    }


    public void setViews(Map<String, View> views) {
        this.views = views;
    }

    public void setApp(VitPub app) {
        this.app = app;
    }
    public String[] getViewNames(){
        Map<String,View> views =getViews();
        Collection<View> myviews = views.values();
        String[] viewnames=new String[myviews.size()];
        int i=0;
        for (Iterator iterator = myviews.iterator(); iterator.hasNext();) {
            View view = (View) iterator.next();
            viewnames[i++]=(view.getName() );
        }
        return viewnames;
    }

    public CoordinationManager getCoordMgr() {
        return this.app.getCoordMgr();
    }


}
